use rusqlite;

#[derive(Debug)]
pub struct KvsLite {
    conn: rusqlite::Connection,

    usql: String,
    isql: String,
    ssql: String,
    dsql: String,
}

impl KvsLite {
    pub fn new(conn: rusqlite::Connection, table_name: &str) -> rusqlite::Result<Self> {
        let _ = conn.execute(
            &format!(
                "CREATE TABLE {} (
                k VARCHAR(32) NOT NULL PRIMARY KEY,
                v TEXT NOT NULL
            )",
                table_name
            ),
            [],
        );

        let usql = format!("UPDATE {} SET v = ?2 WHERE k = ?1", table_name);
        let isql = format!("INSERT INTO {} (k, v) VALUES (?1, ?2)", table_name);
        let ssql = format!("SELECT v FROM {} WHERE k=?1", table_name);
        let dsql = format!("DELETE FROM {} WHERE k = ?1", table_name);

        Ok(KvsLite {
            conn,
            usql,
            isql,
            ssql,
            dsql,
        })
    }

    pub fn set(&self, k: &str, v: &str) -> rusqlite::Result<()> {
        let n = self.conn.execute(&self.usql, [k, v])?;

        if n == 0 {
            self.conn.execute(&self.isql, [k, v])?;
        }

        Ok(())
    }

    pub fn get(&self, k: &str) -> rusqlite::Result<Option<String>> {
        Ok(self.conn.query_row(&self.ssql, [k], |row| row.get(0))?)
    }

    pub fn remove(&self, k: &str) -> rusqlite::Result<usize> {
        self.conn.execute(&self.dsql, [k])
    }
}
